<html xmlns="http://www.w3.org/1999/xhtml" id="views"
      xmlns:d="docbook">
<head>
    <title>Views</title>
</head>

<body>

<h1>Views</h1>

<!-- Experiment with index terms -->
<d:indexterm zone="views" significance="preferred"><d:primary>Views</d:primary></d:indexterm>
<d:indexterm zone="views" significance="preferred"><d:primary>&lt;view&gt;</d:primary></d:indexterm>
<d:indexterm zone="views" significance="preferred"><d:primary>view class</d:primary></d:indexterm>

<h2>Fundamental Properties</h2>
<p>Views are the fundamental visible elements of Laszlo applications. 
 Anything that is displayed on the canvas is a <tagname link="true">view</tagname>
or extends the view class. A running Laszlo application is thus basically a collection of views that interact with each other.
</p>
<p>
Visually, a <tagname>view</tagname> is a rectangular container. As such it has a height, a width, and a placement, 
which is denoted by the x and y values of its upper left corner.  Views can have background
colors, although by default they are transparent. Transparent views can contain arbitrarily shaped images. 
Thus although views are rectangular, Laszlo applications can have virtually any appearance.</p>
<p>
Logically, views are objects that act as containers. Views may contain other views, called subviews or child views, and may
be associated with <i>resources</i> such as images, audio or video files, and Flash player files in .swf format. Thus although a 
view usually has a visual representation on the canvas, it is also possible to have, for example, a view of zero width and zero height that plays, for example,
an audio file.
</p>


<example title="simple view">
&lt;canvas height="50" width="500"&gt;
  &lt;view width="50" height="50" bgcolor="red"/&gt; 
&lt;/canvas&gt;
</example>

<example title="invisible view">
&lt;canvas height="50"&gt;
  &lt;view height="20" width="20" clickable="true"/&gt;
&lt;/canvas&gt;
</example>

<p>The following example shows that the view, although invisible, is
indeed present.  To prove see that this is so, click in the upper left
corner, and then elsewhere on the canvas.</p>

<example title="clicking on invisible view">
&lt;canvas height="160" debug="true"&gt;
  &lt;debug y="30"/&gt;
  &lt;view height="20" width="20" onclick="Debug.write('howdy')"/&gt;
&lt;/canvas&gt;
</example>

<p>A view is only visible if it has a color or an image assigned to it, and if the height and width are greater than zero.
 For example, the following code displays only two images even though four views are defined. The second and third views exist but
 they are completely transparent. The second has no color assigned to it and the third has zero height. They still, however, effect the
 arrangement of the other two views. </p>

<example class="program" title="invisible views affect placement">
&lt;canvas height="60" width="500"&gt;
  &lt;view width="50" height="50" bgcolor="red"/&gt;  <co>This view is a red square.</co>
  &lt;view width="50" height="50"/&gt;                <co>This view has no visual representation because it has no color, but it still exists and displaces other views.</co>
  &lt;view width="0" height="50" bgcolor="blue"/&gt;  <co>This view has no visual representation because it has no width, but it still exists.</co>
  &lt;view resource="../images/logo.png"/&gt;         <co>This view displays the jpg image.</co>
  &lt;simplelayout axis="x" spacing="5"/&gt; 
&lt;/canvas&gt;
</example>

<h4>Z Axis</h4>

<p>Aside from the x and y axes, there is also a <dfn>z axis</dfn> in
the Laszlo view hierarchy. Two sibling views will overlap; the latter
(in lexical order of the LZX code) will appear on top of the
former. This order can be changed using the
<method>bringToFront</method> and <method>sendToBack</method>
methods:</p>

<example title="Simple Layout">
&lt;canvas height="100"&gt;
  &lt;view bgcolor="red" width="50" height="50" 
        onclick="this.bringToFront()"/&gt;
  &lt;view bgcolor="blue" width="50" height="50" x="20" y="20"/&gt;
  &lt;view bgcolor="green" width="50" height="50" x="40" y="40"
        onclick="this.sendToBack()"/&gt;
&lt;/canvas&gt;
</example>

<p>
There are also methods such as <method>sendBehind</method> and <method>sendInFrontOf</method>, that allow you to move a view in the z-axis more precisely, relative to a specified view:
</p>

<example title="fixme5">
&lt;canvas height="100"&gt;
  &lt;view bgcolor="red" id="red" width="50" height="50" 
        onclick="this.sendInFrontOf(blue)"/&gt;
  &lt;view bgcolor="blue" id="blue" width="50" height="50" x="20" y="20"
        onclick="this.sendInFrontOf(green)"/&gt;
  &lt;view bgcolor="green" id="green" width="50" height="50" x="40" y="40"
        onclick="this.sendBehind(red)"/&gt;
&lt;/canvas&gt;
</example>

<p>Views can also be contained within other views, allowing you to create 
  complex visual elements. Each <glossterm>parent view</glossterm> can have any number of children, and each <glossterm>child view</glossterm> is positioned relative 
  to the top-left corner of its parent, as shown here:</p>

<example class="program" title="view containing other views">
&lt;canvas height="200" width="500"&gt;
  &lt;view bgcolor="red" x="50" y="50" width="100" height="100"&gt;
    &lt;view bgcolor="blue" width="50" height="50"/&gt;
    &lt;view bgcolor="yellow" x="50" y="50" width="60" height="105"&gt;
       &lt;view width="50" height="50" bgcolor="green"/&gt;
    &lt;/view&gt;
   &lt;/view&gt;
&lt;/canvas&gt;
</example>
 <p>
Each child view has one and only one parent view.  The relationship between parent and child views is examined below 
and in later chapters.
</p>
<p>The example above also shows that the width and height of a view
can be different than the dimensions of the bounding box of its child
views. The 'yellow' view is not clipped even though it lies outside
the boundary of its parent. If no width and height are actually
defined for a view, then it adopts the width and height of the
bounding box of its subviews. If clipping is desired, however, then
the attribute <code>clip="true"</code> can be added to the parent:</p>

<example title="using the clip attribute">
&lt;canvas height="150" width="500"&gt;
  &lt;view bgcolor="red" x="50" y="50" width="100" height="100" <em>clip="true"</em>&gt;
    &lt;view bgcolor="blue" width="50" height="50"/&gt;
    &lt;view bgcolor="yellow" x="50" y="50" width="60" height="105"&gt;
       &lt;view width="50" height="50" bgcolor="green"/&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
 
<p>As stated above, views don't need to display an image or color to
affect other views. These types of views are referred to as "blank
views".  In fact, this technique of using blank views to group others
views is used extensively in the sample applications. The code below
shows what happens when <code>bgcolors="red"</code> is removed from the
outermost view.</p>

<example class="program" id="view-5">
&lt;canvas height="200" width="500"&gt;
  &lt;view x="50" y="50" width="100" height="100"&gt;
    &lt;view bgcolor="blue" width="50" height="50"/&gt;
    &lt;view bgcolor="yellow" x="50" y="50" width="60" height="105"&gt;
       &lt;view width="50" height="50" bgcolor="green"/&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>The fact that a view can be assigned  different dimensions than the
bounding box of its subviews, is taken advantage of by other
elements within Laszlo such as constraints (<xref linkend="constraints"><a href="${dguide}constraints.html">constraints</a></xref>) and layouts (<xref linkend="layout-and-design"><a href="${dguide}layout-and-design.html">layouts</a></xref>).
</p>
<p>
To illustrate
this point, the following example has two views with identical
dimensions and subviews. The only difference is their code is that the
top view has a <tagname>simplelayout</tagname> and the second view has a
<tagname>stableborderlayout</tagname>. The simplelayout ignores the width of the parent,
while the stableborderlayout stretches the middle subview so that the
combined width of all three subviews matches the width of their
parent.</p>

<p>
Don't worry if you don't understand how to use the layouts described below; layouts are fully explained in 
<xref linkend="layout-and-design"><a href="${dguide}layout-and-design.html">another chapter</a></xref>.
The crucial point to grasp is that a view can have different dimensions than
the bounding box of its subviews. This fundamental property of the Laszlo view system
comes up in countless situations.
</p>

<example title="layouts and bounding box of subviews">
&lt;canvas height="100" width="500"&gt;
  &lt;view bgcolor="red" width="200" height="30"&gt;
    &lt;view bgcolor="blue" width="30" height="30"/&gt;
    &lt;view bgcolor="yellow" width="30" height="30"/&gt;
    &lt;view bgcolor="blue" width="30" height="30"/&gt;
    &lt;simplelayout axis="x" spacing="0"/&gt; 
  &lt;/view&gt;
  &lt;view bgcolor="red" width="200" height="30" y="50"&gt;
    &lt;view bgcolor="blue" width="30" height="30"/&gt;
    &lt;view bgcolor="yellow" width="30" height="30"/&gt;
    &lt;view bgcolor="blue" width="30" height="30"/&gt;
    &lt;stableborderlayout axis="x"/&gt; 
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
  

<h2>The View Coordinate system</h2>
<p>Starting with the canvas, each view has its own internal 2D coordinate system, with as you would expect, the horizontal axis named x and the 
vertical axis named y. The position of a view is calculated relative to its parent's coordinate system.
</p>
 
<p>
As view hierarchies can get complex, it's important to keep in mind, for any view:</p>
<ol>
<li>where its origin is  </li>
<li>units of measurement</li>
<li>its relationship to parent's coordinate system  </li>
</ol>

<p>
In the simple case where a view is, for example, the child of the
canvas, understanding its origin and coordinate system is simple.
Other cases can get rather subtle &#x2014; as for example when a view's
x or y value is a negative number, or when a parent view changes size.
These cases are explored below.</p>

<h3>Relative positions</h3>

<p>To position the floating view over the clicked view, you can use
the <method>getAttributeRelative</method> method of view to obtain the
x and y coordinates of the view relative to a view other than its
parent. For example, consider the case below:</p>

<example title="relative positions">
&lt;canvas height="350" debug="true"&gt;
  &lt;debug y="60" /&gt;
  &lt;view name="parentView" x="10" bgcolor="blue" height="40" width="40"
   oninit="Debug.write('parentView x is', x)" &gt;
    &lt;view name="childView" x="35" bgcolor="yellow" height="20" width="20"
    oninit="Debug.write('childview x is', x)"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p><varname>childView</varname>'s <attribute>x</attribute> value is
<code>35</code>, but its <attribute>x</attribute> value <i>relative to
the canvas</i> is <code>45</code> (because its parent,
<varname>parentView</varname>, is already 10px in from the canvas's
origin). To place a view <varname>cover</varname> that is a child of
canvas on top of <varname>childView</varname>, give it an
<attribute>x</attribute> value of <code>45</code>, because this is the
same offset relative to <varname>cover</varname>'s parent (the canvas)
that <varname>childView</varname> has relative to the canvas.</p>

 

<h3>Sizing of views</h3>

<p>A view that has no width or height specified will be 0px wide by
0px high:</p>

<pre>
&lt;view/&gt;
</pre>


<p>Either dimension of a view can be set explicitly:</p>

<example executable="false">
&lt;view width="20"/&gt; <co>This view is not visible, because it has a height of zero</co>
&lt;view width="20" height="35"/&gt;
</example>
<p>
If a view's dimension is not explicitly set, and that view contains subviews (or has a resource attached), then the view will automatically scale to the extents of its contents or resource. In this case the yellow view will be 40px wide and 25px high:
</p>
<pre>
&lt;view bgcolor="yellow"&gt;
  &lt;view bgcolor="red" width="10" height="10" x="30" y="15"/&gt;
&lt;/view&gt;
</pre>
<p>
In the case above, the yellow view will resize as its contents resize and move. If a dimension had been set at any point then that axis would not resize. This is an important consideration if a nested view is to be moved while the application is running (e.g. if it is dragged by the user). The size of its parent will adjust as necessary:
</p>
<example title="Resizing View">
&lt;canvas height="100"&gt;
  &lt;class name="dragBox" onmousedown="dragger.apply()"
           onmouseup="dragger.remove()" clickable="true" 
           width="10" height="10" bgcolor="red"&gt;
      &lt;dragstate name="dragger"/&gt;
  &lt;/class&gt;

  &lt;view bgcolor="yellow" y="10" x="10"&gt;
    &lt;dragBox x="30" y="10"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>To get around this problem (in the example of a view that is
dragged), there are two solutions:</p>

<ol>
  <li>Limit the drag area of the view to its parents dimensions, and give its parent an explicit size.</li>
  <li>Make the view that is dragged a child of the canvas, so that it is not embedded in the view hierarchy.</li>
</ol>

<p>There is no way to unset a dimension, so that the view returns to
resizing to its contents automatically.</p>

<p>Even if a view's dimensions are set explicitly, and the contents of
the view are larger than those dimensions, the view will <i>remain the
set size</i>. You can retrieve the <em>computed</em> width or height
using the <method>measureWidth</method> and
<method>measureHeight</method> methods respectively.</p>

<pre>
&lt;view bgcolor="yellow" width="30" height="100" clickable="true"&gt;
  &lt;method event="onclick"&gt;
    Debug.write("Actual Width: " + this.width);
    Debug.write("Actual height: " + this.height);
    Debug.write("Measured Width: " + this.measureWidth());
    Debug.write("Measured Height: " + this.measureHeight());
  &lt;/method&gt;

  &lt;view bgcolor="red" width="10" height="10" x="30" y="15"/&gt;
&lt;/view&gt;
</pre>

<p>If a view attaches a resource (and doesn't have its dimensions
set), then it sizes to its resource.  In this example, if
<code>someimg.jpg</code> is 70px wide by 30px high, the view will also
be 70px wide by 30px high:</p>

<code>
&lt;view resource="someimg.jpg"/&gt;
</code>

<p>In cases where the resource for a view is loaded at run-time (i.e. over HTTP), the view will be 0px wide by 0px high until the resource is loaded. This can cause unexpected behavior if other elements in your application are dependant on the size of the view in question. For example:</p>

<pre>
&lt;canvas&gt;
  &lt;simplelayout axis="y" spacing="2"/&gt;
  &lt;view id="myImageView"/&gt;
  &lt;view width="100" height="20" bgcolor="yellow"/&gt;
  &lt;view width="100" height="20" bgcolor="red"/&gt;
  &lt;button x="10" y="110"&gt;Set Image Now!
    &lt;method event="onclick"&gt;
      myImageView.setSource("someimage.jpg");
      &lt;/method&gt;
  &lt;/button&gt;
&lt;/canvas&gt;
</pre>

<p>
At init time, the yellow view will be positioned at (0, 0), because <code>myImageView</code> will have dimensions of 0px wide by 0px high. When the image is loaded (after the button gets clicked) <varname>myImageView</varname> will resize to accommodate the image, and display the image. Since <varname>myImageView</varname> and the other siblings are being acted on by simplelayout, they will all move down. 
</p>

<p>For more on the subject of assigning resources to views, see 
<xref linkend="media-resources"><a href="${dguide}media-resources.html"> this
chapter</a></xref>.</p>

<h3>Scaling</h3>

<p>Consider the following example, which illustrates the effect of
scaling a view's coordinate system. On each click of the view, the
value of the <attribute>height</attribute> attribute diminishes by
10.</p>

<p>First let's look at a simple example that uses text, because this makes the effect more striking.
As you click on the red rectangle, it shrinks, along with the text inside. But the font size does not change.
The text is smaller relative to the canvas and to the computer screen, but not to its parent view.</p>

<example title="simple scaling wtih text">
&lt;canvas width="700" height="100"&gt;
      &lt;font src="helmetb.ttf" name="helmet"/&gt;
  &lt;view stretches="both" height="100" bgcolor="red" 
           onclick="this.animate('height', -10, 1000 , true )"&gt;
    &lt;attribute name="aspect" value="${unstretchedwidth/unstretchedheight}"/&gt;
    &lt;attribute name="width" value="${ height * aspect}"/&gt;
    &lt;text font="helmet" fontsize="22" resize="true"&gt;
      This is some text
    &lt;/text&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>
Here we have modified the example to further illustrate the same point.  Notice how the width of the green view, as reported by the
debugger, does not change, even as the view visibly shrinks.</p>
<example title="simple scaling with text and colored view">
&lt;canvas width="700" height="300" debug="true"&gt;
      &lt;debug y="120"/&gt;
      &lt;font src="helmetb.ttf" name="helmet"/&gt;
  &lt;view stretches="both" height="100" bgcolor="red" 
           onclick="this.animate('height', -10, 1000 , true );
           debug.write('greenview new width is', greenview.width)"&gt;
    &lt;attribute name="aspect" value="${unstretchedWidth/unstretchedHeight}"/&gt;
    &lt;attribute name="width" value="${ height * aspect}"/&gt;
    &lt;view name="greenview" height="100" width="80" bgcolor="green"/&gt;
    &lt;text font="helmet" fontsize="22" resize="true"&gt;
      This is some text
    &lt;/text&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<h3>Offsets</h3>
<p>
 Every view 
has an internal <glossterm>registration point</glossterm>that is at (0,0) by default, the upper left hand corner of the view. 
This point 
can be changed using the <attribute link="true">xoffset</attribute> and <attribute link="true">yoffset</attribute>
 attributes. In short, the offset attributes are applied to the registration point of the view.
Now, the x and y of this view is actually the 
position of its registration point within the view's parent coordinate system. Here is a simple app that 
demonstrates this. See below for an explanation of what's going on in this program.
</p>
<example title="Offsets and registration point">
&lt;canvas height="250"&gt;
    &lt;view x="100" y="100"
          bgcolor="yellow" xoffset="20" yoffset="20"
          width="100" height="100" &gt;
        &lt;view x="${parent.xoffset}" 
              width="1" height="100%" bgcolor="black" /&gt;
        &lt;view y="${parent.yoffset}" 
              width="100%" height="1" bgcolor="black" /&gt;
         &lt;animatorgroup repeat="-1" &gt;
            &lt;animator attribute="xoffset" duration="1000" to="70" /&gt;
            &lt;animator attribute="xoffset" duration="1000" to="20" /&gt;
         &lt;/animatorgroup&gt;
         &lt;animatorgroup repeat="-1" &gt;
            &lt;animator attribute="yoffset" duration="500" to="70" /&gt;
            &lt;animator attribute="yoffset" duration="500" to="20" /&gt;
         &lt;/animatorgroup&gt;
    &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>
The reason that the intersection point does not move is that the parent view (in this case the canvas) is 
placing the colored view at that point, and that point does not change. it is only the <code>xoffset</code> and <code>yoffset</code>
that are changing, not the <code>x</code> and <code>y</code> of the colored view.
</p>
<p>
Views rotate around the registration point. By default, <code>xoffset</code> and <code>yoffset</code> values are both zero and the 
registration point is in the upper left corner of a each view. Offsets allow you to change the rotation point.  I the example below,
the pivot point of the red square is the origin is its upper left corner; the pivot point of the blue square is its center (where x and y are set to "20").

</p>
 
<example title="Simple Offsets">
&lt;canvas height="100"&gt;
  &lt;view x="60" y="60" height="40" width="40" bgcolor="red"
        onclick="this.rotate.doStart()"&gt;
    &lt;animator name="rotate" attribute="rotation" to="45" duration="500"
              start="false" relative="true"/&gt;
  &lt;/view&gt;
  &lt;view x="60" y="60" height="40" width="40" bgcolor="blue" <em>xoffset="20" yoffset="20"</em>
        onclick="this.rotate.doStart()"&gt;
    &lt;animator name="rotate" attribute="rotation" to="45" duration="500" start="false"
              relative="true"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>Offsets allow the view to be placed
relative to the point (<attribute>xoffset</attribute>,
<attribute>yoffset</attribute>).  (Otherwise the view is placed using
the view's top left corner as a reference point.)  If a view has an
offset, then this will effect how layouts position it relative to
other views.  See for example <tagname link="true">constantboundslayout</tagname>.
</p>

<h2>Positioning of Views</h2>
<p>
There are a variety of ways to set the position of a view. You can explicitly set its x and y values using tags; you can
constrain the x and y values to values of other attributes, including those contained in a dataset, you can use layouts which "let the system"
determine a view's position, or you can change the position  at runtime by using script.</p>

<ul>
  <li>Declaratively
  <ul>
    <li>Using absolute x and y values</li>
    <li>Using constraints</li>
    <li>Using path constraints</li>
    <li>Using layouts</li>
  </ul>
  </li>
  <li>Programmatically
  <ul>
    <li>Using <method>setAttribute</method></li>
    <li>Instantiating from script</li>
  </ul>
  </li>
</ul>

<h3>Declarative positioning of views using absolute coordinates</h3>
 
<p>
You can position views using absolute x and y coordinates, and the view will be positioned relative to its parent's origin:
</p>
<example title="absolute positioning">
&lt;canvas&gt;
  &lt;view bgcolor="yellow" width="300" height="300" x="15" y="20"&gt;
    &lt;view bgcolor="red" width="20" height="20" x="<b>25</b>" y="<b>75</b>"/&gt;

    &lt;view bgcolor="blue" width="20" height="20" x="<b>75</b>" y="<b>200</b>"/&gt;

    &lt;view bgcolor="green" width="20" height="20" x="<b>50</b>" y="<b>50</b>"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>


<h3>Declarative positioning of views using constraints</h3>
<p>

You can also use constraints to position views. In the example below, the red view's position is set absolutely,
the blue view's and y positions are constrained to a function of the red view's coordinates.
</p>
<example title="Using constraints to position views">
&lt;canvas&gt;
  &lt;view bgcolor="yellow" width="300" height="300"&gt;
    &lt;attribute name="someXValue" type="number" value="50"/&gt;

    &lt;view bgcolor="red" name="red" width="20" height="20" 
            x="<b>$once{20 + 5}</b>" y="<b>$once{70 + 5}</b>"/&gt;

    &lt;view bgcolor="blue" width="20" height="20" 
            x="<b>${parent.red.y}</b>" y="<b>${parent.red.x}</b>"/&gt;

    &lt;view bgcolor="green" width="20" height="20" 
            x="<b>${parent.someXValue}</b>" y="<b>${this.x}</b>"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>
In the example above,
</p>
<ul>
<li>The red <varname>x</varname> and <varname>y</varname> coordinates
are constrained to mathematical expressions (20+5 and 70+5
respectively). </li>
<li>The blue view's <varname>x</varname> and <varname>y</varname> coordinates are constrained to the red view's <varname>y</varname> and <varname>x</varname> coordinates respectively.</li>
<li>The green view's <varname>x</varname> and <varname>y</varname> coordinates are constrained to some arbitrary attribute value.</li>
</ul>


<p>See <xref linkend="constraints"/> for more on constraint syntax.</p>
 
<h3>Negative coordinate values</h3>
<p>
The x and y values can be set to negative values. In the example below, clicking on the square causes successive views
to appear and to move left or right.  The parent square (teal color) expands to contain the blue and black squares,
but not to contain the red and silver squares, which have negative x and y values.</p>
<example title="Positive and negative offsets">
&lt;canvas height="250" bgcolor="gray"&gt;
  &lt;view x="100" y="100" bgcolor="teal"&gt;
    &lt;view bgcolor="red" width="20" height="20"
            onclick="this.animate('y' , -50 , 1000, true)"/&gt;
    &lt;view bgcolor="silver" width="20" height="20"
            onclick="this.animate('x' , -50 , 1000, true)"/&gt;
    &lt;view bgcolor="blue" width="20" height="20"
            onclick="this.animate('y' , 50 , 1000, true)"/&gt;
    &lt;view bgcolor="black" width="20" height="20"
            onclick="this.animate('x' , 50 , 1000, true)"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example> 
<h2>View Hierarchy</h2>
<p>Each view has a position in the <i>view hierarchy</i>, that is, the tree structure of objects in which each view has
a parent, and, optionally, children and or sibling views. In simple cases such as the following the relationship of 
parents and children is obvious from their position in the code.</p>
<example title="simple view hierarchy">
&lt;canvas height="100"&gt;
   &lt;view height="100" width="100" name="grandparent" bgcolor="red"&gt;
      &lt;view height="50" width="50" name="parent" bgcolor="green"&gt;
        &lt;view height="30" width="30" name="child" bgcolor="blue"/&gt;
      &lt;/view&gt;
    &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>However, things are usually more complicated, especially when views are created within classes. Views can be created or destroyed at runtime, and moreover a single
line of code can cause the creation of an arbitrary number of views. In many cases there are, in effect, two hierarchies-
the <i>lexical hierarchy</i> of views in the code, and the <i>node hierarchy</i> of objects that are created by the code.
</p>
<p>
LZX employs the terms <i>parent</i> and <i>immediate parent</i> to distinguish between a view's relationship in different
hierarchies.  These terms are explained in greater depth in later chapters, but here's a short preview.</p>


<h3>Children and Parents</h3>

<example title="Parent and Immediate Parent">
&lt;canvas height="100"&gt;
  &lt;class name="mywindow"
        onmousedown="dragger.apply()" onmouseup="dragger.remove()"
        bgcolor="blue"&gt;
    &lt;dragstate name="dragger"/&gt;

    &lt;attribute name="defaultplacement" value="mycontent" type="string"/&gt;

    &lt;view name="mycontent" x="10" y="10" bgcolor="white"
             width="${parent.width-20}" height="${parent.height-20}"&gt;
      <co>default placement view: instance or subclass children go here</co>
    &lt;/view&gt;
  &lt;/class&gt;

  &lt;mywindow id="w" width="100" height="100"&gt;
    &lt;text&gt;hello&lt;/text&gt;
  &lt;/mywindow&gt;
&lt;/canvas&gt;
</example>

<p>The view that contains the text <code>hello</code> has a
<attribute>parent</attribute> of <varname>w</varname> and an
<attribute>immediateparent</attribute> of <code>w.mycontent</code>.
Note that "mycontent" could be nested in other views and it would
still work.  We call this ordering of objects the "node hierarchy." The term "view hierarchy" is more intuitive, but "node
hierarchy" is more correct.  (Notice that in the above example,
"dragger" is a node, not a view)</p>

<p>If you're an experienced javascript programmer you will have seen this pattern before. 
When you see "immediateParent" in JavaScript, think "container".</p>

<p> Similarly, if you've looked at XAML, you may have seen that
XAML distinguishes between the logical tree and the visual tree.  The logical tree corresponds to the hierarchy as represented in the source (what we have sometimes called the source hierarchy). 
 The visual hierarchy corresponds to the hierarchy as rendered.</p>

<p>Given this class definition:</p>
<example title="Simple placement">
&lt;canvas height="60"&gt;
  &lt;class name="myclass"&gt;
    &lt;simplelayout/&gt;
    &lt;view name="content"/&gt;
    &lt;text&gt;label&lt;/text&gt;
  &lt;/class&gt;
    
   &lt;myclass&gt;&lt;text placement="content"&gt;content1&lt;/text&gt;&lt;/myclass&gt;
   &lt;myclass&gt;&lt;text placement="content"&gt;content2&lt;/text&gt;&lt;/myclass&gt;
   &lt;simplelayout axis="y"/&gt;
&lt;/canvas&gt;
</example>
 
<p>this source fragment:</p>

<example executable="false">
&lt;myclass&gt;&lt;text placement="content"&gt;content1&lt;/text&gt;&lt;/myclass&gt;
&lt;myclass&gt;&lt;text placement="content"&gt;content2&lt;/text&gt;&lt;/myclass&gt;
</example>

<p>has the logical tree:</p>
<pre>
myclass (text "content1")
myclass (text "content2")
</pre>
<p>and the visual tree:</p>
<pre>
myclass (view (text "content1") (text "label")
myclass (view (text "content2") (text "label")
</pre>


<p>Thus <attribute>parent</attribute> refers to the parent in the
logical tree.  <code>immediateParent</code> (in JavaScript) and
<attribute>placement</attribute> (in XML) refers to the parent in the
visual tree. Placement is similar to, but not exactly the same as immediateparent.  You
can think of them as meaning the same thing with different types, but
just to be clear: placement is a string which means: "find the view in
my parent's children (or any descendant) which has this name, and when
I am created make me a child of that view."  immediateparent is then a
reference to that view.</p>

<p>placement is an instruction from a view to its parent about
where it belongs within the parent's internal hierarchy. By default, this is
interpreted to mean: 'find the subview with this name', but the parent is free
to interpret it however it wants.</p>

<p>These concepts are explained in greater detail, and with several
more examples, in the chapter on extending classes.</p>
 <h3>Creating an array of subviews</h3>

<h2>Views and Nodes</h2>
<p>In LZX, the fundamental objects are called nodes. Nodes are abstract entities and as such they have no visual representation. Views are the most common kind of node, and in most cases
you when you need a container object, you should use a view even though a node would work. In fact, although 
you can use <tagname>node</tagname>s for most of the abstract
infrastructure (dataset manipulation, content management, polling, etc.)
but currently, the compiler complains when putting datapointers and
datasets in nodes.  
Nodes are only created
through script; there is no tag for creating them.</p>
<p> 
As discussed in later chapters, in situations when you are trying to squeeze out the last lit of performance, you may want to
examine how much overhead is there in using a view vs. a node (when there's no
presentation associated with the element)</p>



 <h2>How views are built</h2>

<p>
Sometimes it's important to understand the sequence that takes place
when views are created.  This is explained in depth in <xref
linkend="initialization-and-instantiation"/>, but here's a brief
summary:</p>

<p>The evaluation of a view occurs in three phases:</p>

<ol>
  <li><p><glossterm baseform="construction">Construction</glossterm>:
  The
  object representing the view is created, and attributes with
  constant initial values are filled in.</p></li>
  
  <li><p><glossterm baseform="instantiation">Instantiation</glossterm>:
  The attributes
  with dynamic initial values are filled in (which includes the
  construction and instantiation of any child views), the
  <method>initialize</method> method is executed, and the
  <event>onconstruct</event> event is sent.</p></li>
  
  <li><p><glossterm>Initialization</glossterm>:
  The
  <method>init</method> method is executed and the
  <event>oninit</event> event is sent.</p>
  </li>
</ol>

<p>
   Note that  construction  and  instantiation  occur
   sequentially, but that  initialization  may be arbitrarily
   delayed, depending on the value of the  <attribute>initstage </attribute> attribute.
   Attributes with dynamic initial values may not depend on other
   attributes with dynamic initial values, nor on the <method>initialize</method>
   or <method>init</method> methods having been run. 
</p>
 <h3>Adding subviews</h3>
<p>When an view is built, <code>subviews[] </code>is initialized to an empty array. (In releases before OpenLaszlo 3.0 it was null.)</p>
<p><method>addSubview</method> is like an event handler; it's a protected method of view that is called when a view is added to its 
parent. You can't call it directly, but you can override it.  However, in most cases you will want to use
the <attribute>onaddsubview</attribute> event instead.</p>
<h2>Distinguishing features of Laszlo's Coordinate System</h2>

<p>If you have experience doing graphics programming, you may be interested in the following paragraph.
Otherwise you can safely skip this topic.</p>
<p>Laszlo's coordinate system is distinctive in that 'rotate' and 'xscale', and 'yscale' are the primitives for
defining the coordinate system within a view.  Other systems define
only a translation, or only a translation and scale, or allow an
arbitrary 3x2 or 3x3 transformation.  Laszlo is distinctive both in
not defining a translation ('x' and 'y' position the bounds of the
view within its parent as well as defining a translation that precedes
the rotate/scale, so it can't be used for this), and in representing
the matrix in terms of its ops (which leaves some gaps, such
as skew &#x2014; but is much better for animation, which requires a
much heavier-duty symbolic mechanism in SVG).</p>
<p>
The fact that resources aren't child views leads to some 
tension in the system, where 
designers expect them to be view-like, and there's a pull to make them view-like by adding rotation or
 translation to them that's independent of the view that embeds them, and to make it possible to 
retrieve their bounds.  (This is largely independent from the fact that they're represented as ids 
instead of objects.)   
</p> 

 



</body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
